package top.fangwenmagician.calculationstring;

import top.fangwenmagician.calculationstring.log.F_LogProcessing;
import top.fangwenmagician.calculationstring.log.I_CalculationLog;

/**
 * <h1>流程控制器</h1>
 * 主要用于回调计算和写入日志。<br /><br />
 * <h2>日志</h2>
 * {@link ProcessControl}实现了{@link I_CalculationLog}接口，可直接当作log对象使用。<br />
 * 从{@link I_CalculationLog}接口上实现的方法也会自动验空，当{@link ProcessControl#log}变量为空时方法不会报错。<br />
 * 与直接使用log对象不同，在{@link ProcessControl#logProcessing}不为null时，会通过该对象处理要写入的日志字符串。<br /><br />
 * <h2>回调计算</h2>
 * {@link ProcessControl}实现了{@link I_CalculationString}接口，
 * 可以通过{@link ProcessControl#calculation(String)}或者{@link ProcessControl#calculation(String, I_CalculationLog)}函数
 * 进行回调计算。<br />
 * 其使用的{@link CalculationString}对象和触发运算发的是同一个。<br /><br />
 * <h2>获取和更改配置对象</h2>
 * {@link ProcessControl}实现了{@link I_CalculationConfigure}接口。<br />
 * 可以通过{@link ProcessControl#getConfigure()}或{@link ProcessControl#getConfigure(Class)}来获取配置。<br />><br />
 */
public class ProcessControl implements I_CalculationString, I_CalculationLog, I_CalculationConfigure {
    /**
     * 计算所使用的{@link CalculationString}对象
     */
    private final CalculationString calculationString;
    /**
     * 用于加工log的对象
     */
    private F_LogProcessing logProcessing;
    /**
     * 日志对象
     */
    private I_CalculationLog log;

    public ProcessControl(CalculationString calculationString, I_CalculationLog log) {
        this.calculationString = calculationString;
        this.log = log;
    }

    @Override
    public String calculation(String expression) throws Exception {
        return calculationString.calculation(expression);
    }

    @Override
    public <T extends I_CalculationLog> String calculation(String expression, T log) throws Exception {
        return calculationString.calculation(expression, log);
    }

    @Override
    public void writeLog(String logText) throws Exception {
        if (log != null) {
            if (logProcessing == null) {
                log.writeLog(logText);
            } else {
                log.writeLog(logProcessing.processing(logText));
            }
        }
    }

    @Override
    public String removeLast() throws Exception {
        if (log != null) {
            return log.removeLast();
        } else {
            return null;
        }
    }

    @Override
    public Object getConfigure() {
        return calculationString.getConfigure();
    }

    @Override
    public <T> T getConfigure(Class<T> tClass) {
        return calculationString.getConfigure(tClass);
    }

    public CalculationString getCalculationString() {
        return calculationString;
    }

    public I_CalculationLog getLog() {
        return log;
    }

    public <T extends I_CalculationLog> T getLog(Class<T> logClass) {
        return logClass.cast(log);
    }

    public <T extends I_CalculationLog> void setLog(T log) {
        this.log = log;
    }

    public F_LogProcessing getLogProcessing() {
        return logProcessing;
    }

    public void setLogProcessing(F_LogProcessing logProcessing) {
        this.logProcessing = logProcessing;
    }
}
